/*******************************************************************************
 * Copyright (c) 2006 CEA List.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     CEA List - initial API and implementation
 *******************************************************************************/
package com.cea.papyrus.tabbedproperties.section;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.eclipse.core.runtime.IStatus;
import org.eclipse.gef.commands.Command;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CLabel;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.ui.views.properties.tabbed.TabbedPropertySheetPage;
import org.eclipse.uml2.uml.Element;
import org.eclipse.uml2.uml.Interface;
import org.eclipse.uml2.uml.Port;

import com.cea.papyrus.core.IPapyrusUIConstants;
import com.cea.papyrus.core.PapyrusPlugin;
import com.cea.papyrus.core.commands.factories.DiagramElementDeleteCommandFactory;
import com.cea.papyrus.core.editor.CommandStackUtils;
import com.cea.papyrus.core.tabbedproperties.PropertyViewSection;
import com.cea.papyrus.core.utils.Debug;
import com.cea.papyrus.core.utils.LookForElement;
import com.cea.papyrus.diagraminterchange2.di2.Diagram;
import com.cea.papyrus.diagraminterchange2.di2.GraphElement;
import com.cea.papyrus.diagraminterchange2.di2.GraphNode;

/**
 * This class is used to display provided and required Interfaces of a port
 * Those lists cannot be modified. To do that the user has to modified class diagram.
 */
public class PortInterfaceSection extends PropertyViewSection{

	/** Image for the "View element" Button  */
	private final Image IMG_DISPLAY	= PapyrusPlugin.getImage(PapyrusPlugin.PAPYRUS_ICONS_16x16+"ConsoleView_16x16.gif");

	/**Button used to add an interface into the diagram */
	protected Button viewElementButton;

	/** required interface label */
	private final String REQUIRED_INTERFACES="Required Interfaces: ";

	/** provided interface label*/
	private final String PROVIDED_INTERFACES="Provided Interfaces: ";

	/** separator for the section */
	private org.eclipse.swt.widgets.Label separator;

	/** Tree that displays the required interfaces for the port */
	private Tree requiredInterfaceTree;

	/** Tree that displays the provided interfaces for the port */
	private Tree providedInterfaceTree;

	/**
	 * 
	 * 
	 * @param tabbedPropertySheetPage 
	 * @param parent 
	 */
	@Override
	public void createControls(Composite parent,
			TabbedPropertySheetPage tabbedPropertySheetPage) {
		//init the creation
		super.createControls(parent, tabbedPropertySheetPage);
		final Composite composite = getWidgetFactory().createFlatFormComposite(parent);

		viewElementButton = getWidgetFactory().createButton(composite, "", SWT.PUSH);
		viewElementButton.setVisible(true);
		viewElementButton.setImage(IMG_DISPLAY);
		viewElementButton.setToolTipText("View Element");
		//add the first label
		FormData data;
		//label for required interface
		CLabel requiredInterfacesLabel = getWidgetFactory().createCLabel(composite, REQUIRED_INTERFACES); 
		data = new FormData();
		data.left = new FormAttachment(0, 0);
		data.top = new FormAttachment(0, 0);
		requiredInterfacesLabel.setLayoutData(data);

		//add view Button
		data= new FormData();
		data.top  = new FormAttachment(0, 0);
		data.left = new FormAttachment(requiredInterfacesLabel,150);
		viewElementButton.setLayoutData(data);

		separator = getWidgetFactory().createSeparator(composite, SWT.VERTICAL);
		separator.setVisible(false);
		data = new FormData();
		data.left = new FormAttachment(30);
		data.top = new FormAttachment(0, 0);
		data.bottom = new FormAttachment(100);
		separator.setLayoutData(data);


		// add tree to represent requiredInterface
		requiredInterfaceTree = getWidgetFactory().createTree(composite, SWT.NONE);
		data = new FormData(300, 100);
		data.left = new FormAttachment(0, 0);
		data.bottom = new FormAttachment(100);
		data.top = new FormAttachment(viewElementButton, 0);
		requiredInterfaceTree.setLayoutData(data);

		viewElementButton.addMouseListener(new ViewElementButtonListener(requiredInterfaceTree) );


		///
		viewElementButton = getWidgetFactory().createButton(composite, "", SWT.PUSH);
		viewElementButton.setVisible(true);
		viewElementButton.setImage(IMG_DISPLAY);
		viewElementButton.setToolTipText("View Element");


		//label for provided interfaces
		CLabel providedInterfacesLabel = getWidgetFactory().createCLabel(composite,PROVIDED_INTERFACES); 
		data = new FormData();
		data.left = new FormAttachment(requiredInterfaceTree, 60);
		data.top = new FormAttachment(0, 0);
		providedInterfacesLabel.setLayoutData(data);

		//add view Button
		data= new FormData();
		data.top  = new FormAttachment(0, 0);
		data.left = new FormAttachment(providedInterfacesLabel,150);
		viewElementButton.setLayoutData(data);

		separator = getWidgetFactory().createSeparator(composite, SWT.VERTICAL);
		separator.setVisible(false);
		data = new FormData();
		data.left = new FormAttachment(30);
		data.top = new FormAttachment(0, 0);
		data.bottom = new FormAttachment(100);
		separator.setLayoutData(data);


		// add tree to represent providedInterface
		providedInterfaceTree = getWidgetFactory().createTree(composite, SWT.NONE);
		data = new FormData(300, 100);
		data.left = new FormAttachment(requiredInterfaceTree, 60);
		data.bottom = new FormAttachment(100);
		data.top = new FormAttachment(viewElementButton, 0);
		providedInterfaceTree.setLayoutData(data);
		viewElementButton.addMouseListener(new ViewElementButtonListener(providedInterfaceTree) );
	}

	/* (non-Javadoc)
	 * @see org.eclipse.ui.views.properties.tabbed.AbstractPropertySection#refresh()
	 */
	@Override
	public void refresh() {
		if(!requiredInterfaceTree.isDisposed() && !providedInterfaceTree.isDisposed()){
			// required and provided interface trees refresh
			requiredInterfaceTree.removeAll();
			providedInterfaceTree.removeAll();

			// look for for all required and provided interfaces of the port
			if(((Port)getElement())!=null){
				// provided and required interface tree refresh
				refreshInterfaceTree(((Port)getElement()).getRequireds(), requiredInterfaceTree);
				refreshInterfaceTree(((Port)getElement()).getProvideds(), providedInterfaceTree);
			} 
		}
	}

	/**
	 * Refresh Tree for the given collection of interfaces, and for the specified tree
	 * @param interfaces the interfaces to be displayed
	 * @param parentTree the tree where to display the interfaces
	 */
	protected void refreshInterfaceTree(List<Interface> interfaces, Tree parentTree) {
		for(int i=0; i<interfaces.size(); i++){
			// create an item for each required interface found
			TreeItem stItem = new TreeItem(parentTree, SWT.NONE);
			final Interface currentInterface = interfaces.get(i);
			if(labelProvider!=null) {
				stItem.setImage(labelProvider.getImage(currentInterface));
			} else {
				Debug.log(IStatus.WARNING, "impossible to find a label provider for "+currentInterface);
			}
			// display interface name + the package location	
			stItem.setText(currentInterface.getName()+"     (from "+currentInterface.getNearestPackage().getName()+")");
			stItem.setData(currentInterface);
		}
	}


	/**
	 * The Class ViewElementButtonListener.
	 */
	private class ViewElementButtonListener implements MouseListener {

		protected Tree table;

		public ViewElementButtonListener(Tree table){
			this.table=table;
		}

		/**
		 * Mouse double click.
		 * 
		 * @param e the e
		 */
		public void mouseDoubleClick(MouseEvent e) {
			// do nothing
		}

		/**
		 * Mouse down.
		 * 
		 * @param e the e
		 */
		public void mouseDown(MouseEvent e) {
			// do nothing
		}

		/**
		 * Mouse up.
		 * 
		 * @param e the e
		 */
		public void mouseUp(MouseEvent e) {
			// if there is no graphics, it is not use to draw a link

			//0. the diagramElement is a label or a port?
			GraphElement di2Port=null;
			if (((GraphElement)diagramElement).getSemanticModel()!=null){
				di2Port=(GraphElement)diagramElement;
			}
			else{
				di2Port =(GraphElement) diagramElement.getSemanticParent();
			}
			//go accros tree
			TreeItem[] tableItems = this.table.getSelection();
			for (int i=0; i< tableItems.length;i++){
				//1. get Selected item

				Element UMLElement=(Element)tableItems[i].getData();
				Diagram currentDiagram= LookForElement.getDiagram((GraphNode)diagramElement);
				final String typeDiagram = currentDiagram.getType();
				ArrayList found=LookForElement.lookForGraphElement(UMLElement, currentDiagram, new ArrayList());

				//2. the graphical element already exist?
				GraphElement di2Interface =null;
				Iterator itfound=found.iterator();
				while(itfound.hasNext()){
					GraphElement currentElement= (GraphElement)itfound.next();
					if (currentElement.getSemanticParent().equals(di2Port)){
						di2Interface=currentElement;
					}
				}
				if( di2Interface==null){
					// 3. we have to create the graphical Element
					//    effective command depends on current diagram

					if (IPapyrusUIConstants.COMPOSITE_STRUCTURE_DIAGRAM.equals(typeDiagram)) {
						Command addcmd= new  com.cea.papyrus.diagram.composite.command.InterfaceDisplayCommand(di2Port,(Interface)UMLElement,currentDiagram);
						CommandStackUtils.getCommandStack().execute(addcmd);
					}
					else if (IPapyrusUIConstants.COMPONENT_DIAGRAM.equals(typeDiagram)) {
//						Command addcmd= new  com.cea.papyrus.diagram.composite.command.InterfaceDisplayCommand(di2Port,(Interface)UMLElement,currentDiagram);
						Command addcmd= new  com.cea.papyrus.diagram.component.command.InterfaceDisplayCommand(di2Port,(Interface)UMLElement,currentDiagram);
//						Command addcmd= new  com.cea.papyrus.diagram.component.command.InterfaceDisplayCommand(di2Port,(Interface)UMLElement,di2Port.getContainer());
						CommandStackUtils.getCommandStack().execute(addcmd);
					} 
				}     

				//3. we have to delete this element
				else{
					Command deletecmd=DiagramElementDeleteCommandFactory.eINSTANCE.createCommand(di2Interface);
					CommandStackUtils.getCommandStack().execute(deletecmd);
				}

			}
		}

	}


}
